package com.zjmzxfzhl.modules.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zjmzxfzhl.common.core.constant.SysConstants;
import com.zjmzxfzhl.common.core.exception.SysException;
import com.zjmzxfzhl.common.core.util.CommonUtil;
import com.zjmzxfzhl.common.core.util.SecurityUtils;
import com.zjmzxfzhl.modules.app.entity.*;
import com.zjmzxfzhl.modules.app.form.*;
import com.zjmzxfzhl.modules.app.platform.MailinaboxUserUtils;
import com.zjmzxfzhl.modules.app.service.*;
import com.zjmzxfzhl.modules.sys.entity.SysUser;
import com.zjmzxfzhl.modules.sys.entity.vo.ElTree;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zjmzxfzhl.common.core.base.BaseServiceImpl;
import com.zjmzxfzhl.modules.app.mapper.AppProjMapper;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Service
 * 
 * @author 张森荣
 */
@Service
public class AppProjServiceImpl extends BaseServiceImpl<AppProjMapper, AppProj>
        implements AppProjService {

    @Value("${mailinabox.postfix}")
    private  String postfix; //邮箱后缀

    @Autowired
    private AppProjUserService appProjUserService;
    @Autowired
    private AppProjTagService appProjTagService;
    @Autowired
    private AppTaskService appTaskService;
    @Autowired
    private AppMptService appMptService;
    @Autowired
    private AppLogService appLogService;
    @Autowired
    private MailinaboxUserUtils mailinaboxUserUtils;
    @Autowired
    private AppDocService appDocService;
    @Autowired
    private AppTemplateService appTemplateService;
    @Autowired
    private AppTaskTagService appTaskTagService;

    @Override
    public IPage<AppProj> list(IPage<AppProj> page, AppProjVo appProj) {
        return page.setRecords(baseMapper.list(page, appProj));
    }

    public Integer selectRowCount(AppProj appProj) {
        return baseMapper.selectRowCount(appProj);
    }
    public ProjSumVo getProjSun(String masterUserId) {
        return baseMapper.getProjSun(masterUserId);
    }
    public  List<AppProj> getMeetProj(String[] idsArr) {
        return baseMapper.getMeetProj(idsArr);
    }
    /**
     * 新增项目，自动计算机构级别、机构级次码、是否叶子
     *
     * @param appProj
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveAppProj(AppProj appProj) {
        //保存项目成员数组，标签数组
        List<SysUser> userList=null;
        List<AppTag> tags=null;
        List<DocFilePath> docFilePaths= null;
        String tempDirId=null;
        if(appProj.getUserList()!=null){
            userList=appProj.getUserList();
        }
        if(appProj.getTags()!=null){
           tags=appProj.getTags();
        }
        if(appProj.getDocFilePath()!=null){
            docFilePaths=appProj.getDocFilePath();
        }
        if (appProj.getTempDirId() != null && !"".equals(appProj.getTempDirId())) {
            tempDirId = appProj.getTempDirId();
        }
        //添加项目
        appProj =setAppProj(appProj);
        Boolean result = this.save(appProj);
        if(result==false){
            return result;
        }
        // 【1】 校验id是否重复.
        appProj=this.getById(appProj.getProjId());
        if (CommonUtil.isEmptyStr(appProj.getParentProjId())) {
            appProj.setProjLevel("1");
            appProj.setProjLevelCode(appProj.getProjId());
            appProj.setIsLeaf(SysConstants.USER_STATUS_1);
            result = this.updateById(appProj);
        } else {

            // 父节点
            AppProj parentAppProj = this.getById(appProj.getParentProjId());
            if (parentAppProj == null) {
                throw new SysException("保存失败,上级机构ID【" + appProj.getParentProjId() + "】不存在!");
            }
            // 【2】计算机构级次,机构级次码
            // 【2-a】设置新增机构的父机构是否叶子为否
            if (!SysConstants.IS_LEAF_0.equals(parentAppProj.getIsLeaf())) {
                parentAppProj.setIsLeaf(SysConstants.IS_LEAF_0);
                this.updateById(parentAppProj);
            }
            Integer projLevel = Integer.valueOf(parentAppProj.getProjLevel()) + 1;
            appProj.setProjLevel(projLevel.toString());
            appProj.setProjLevelCode(parentAppProj.getProjLevelCode() + "," + appProj.getProjId());

            // 【3】设置新增机构是否叶子为 是；
            appProj.setIsLeaf("1");
            result = this.updateById(appProj);

            //判断是否存在非父项目成员
            if (!appProjUserService.checkMembers(userList, appProj.getParentProjId())) {
                throw new SysException("存在不属于父项目的参与成员！");
            }
            //判断负责人是否为父项目成员
            if (appProj.getMasterUserId() != null && !"".equals(appProj.getMasterUserId())) {
                List<String> projUserIdList = appProjUserService.selectUserIdList( appProj.getParentProjId());
                    if (!projUserIdList.contains(appProj.getMasterUserId())) {
                        throw new SysException("负责人不属于父项目的参与成员！");
                    }
            }
        }
        //添加项目成员，项目标签
        if(userList!=null){
            for (SysUser user:userList) {
                AppProjUser appProjUser=new AppProjUser();
                appProjUser.setProjId(appProj.getProjId());
                appProjUser.setUserId(user.getUserId());
                appProjUserService.saveAppProjUser(appProjUser);
            }
        }
        if(tags!=null){
            for (AppTag tag:tags) {
                AppProjTag appProjTag=new AppProjTag();
                appProjTag.setProjId(appProj.getProjId());
                appProjTag.setTagId(tag.getTagId());
                appProjTagService.saveAppProjTag(appProjTag);
            }
        }

        //添加项目附件
        if (docFilePaths != null && docFilePaths.size() > 0) {
            AppDoc appDoc=new AppDoc();
            appDoc.setDocFilePath(docFilePaths);
            appDoc.setDeleted("0");
            appDoc.setName(docFilePaths.get(0).getFileName());
            appDoc.setDirId(appProj.getDirId());
            appDoc.setDocType("00");
            appDoc.setDocTypeId(appProj.getProjId());
            appDoc.setContent("项目: "+appProj.getName()+"的附件");
            appDocService.saveAppDoc(appDoc);
        }

        //使用模板
        if(tempDirId!=null){
            useTemplate(appProj.getProjId(),tempDirId);
        }

        //添加项目邮箱
        String mailbox=appProj.getProjSn()+"@"+postfix;;

        String password=UUID.randomUUID().toString().replace("-", "").toLowerCase();
        appProj.setMailbox(mailbox);
        appProj.setMailPassword(password);

        //创建邮箱
        try {
            String str= mailinaboxUserUtils.addUsers(mailbox,password,"");
            if(!"mail user added\n".equals(str)){
                if("User already exists.".equals(str)){
                    throw new SysException("电子邮件已存在！请修改项目编号！");
                }
                if("Invalid email address.".equals(str)){
                    throw new SysException("无效的电子邮件地址！请修改项目编号！");
                }
                throw new SysException(str);
            }
        }catch (Exception e){
            throw new SysException(e.getMessage());
        }
        this.updateById(appProj);

        return result;
    }

    private AppProj setAppProj(AppProj appProj){
        if (appProj.getStatus() == null || "".equals(appProj.getStatus())) {
            appProj.setStatus("00");
        }
        if (appProj.getProjLevel() == null || "".equals(appProj.getProjLevel())) {
            appProj.setProjLevel("0");
        }
        if (appProj.getProjLevelCode() == null) {
            appProj.setProjLevelCode("");
        }
        //默认可修改
        if (appProj.getRevise() == null || "".equals(appProj.getRevise())) {
            appProj.setRevise("1");
        }
        if (appProj.getMailbox() == null) {
            appProj.setMailbox("");
        }
        if (appProj.getMailPassword() == null) {
            appProj.setMailPassword("");
        }
        return appProj;
    }

    /**
     * 移动机构树，自动计算机构级别、机构级次码、是否叶子
     *
     * @param appProj
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean moveTree(AppProj appProj,String parentId) {
        Boolean result = true;

        if (CommonUtil.isEmptyStr(appProj.getParentProjId())) {
            appProj.setProjLevel("1");
            appProj.setProjLevelCode(appProj.getProjId());
            result = this.updateById(appProj);
        } else {
            // 父节点
            AppProj parentAppProj = this.getById(appProj.getParentProjId());
            if (parentAppProj == null) {
                throw new SysException("保存失败,上级机构ID【" + parentAppProj.getParentProjId() + "】不存在!");
            }
            // 【2】计算机构级次,机构级次码
            // 【2-a】设置新增机构的父机构是否叶子为否
            if (!SysConstants.IS_LEAF_0.equals(parentAppProj.getIsLeaf())) {
                parentAppProj.setIsLeaf(SysConstants.IS_LEAF_0);
                this.updateById(parentAppProj);
            }
            Integer ProjLevel = Integer.valueOf(parentAppProj.getProjLevel()) + 1;
            appProj.setProjLevel(ProjLevel.toString());
            appProj.setProjLevelCode(parentAppProj.getProjLevelCode() + "," + appProj.getProjId());
            result = this.updateById(appProj);
        }
        if (result == true) {
            //不为叶子节点时更改子树的层级，路径
            if (SysConstants.IS_LEAF_0.equals(appProj.getIsLeaf())) {
                AppProjVo selectProj = new AppProjVo();
                selectProj.setProjLevelCode(appProj.getProjId());

                List<AppProj> appProjList = baseMapper.list(null, selectProj);
                if (appProjList.size() > 0) {
                    for (AppProj Proj : appProjList) {
                        if (Proj.getProjLevelCode().indexOf(appProj.getProjId()) != -1) {
                            //替换树路径
                            int sub = Proj.getProjLevelCode().indexOf(appProj.getProjId()) + appProj.getProjId().length();
                            Proj.setProjLevelCode(appProj.getProjLevelCode() + Proj.getProjLevelCode().substring(sub));
                            //根据树路径修改层级
                            String[] codeArr = Proj.getProjLevelCode().split(",");
                            Integer level = codeArr.length;
                            Proj.setProjLevel(level.toString());
                            this.updateById(Proj);
                        }
                    }
                }
            }
        }
        //判断原父节点是否成为新为叶子
        if (parentId != null && !"".equals(parentId)) {
            inspectParent(parentId);
        }
        return result;
    }


    /**
     * 机构管理，机构树数据
     *
     * @return
     */
    @Override
    public List<ElTree> getTreeData(AppProjVo appProj,Integer current, Integer size, String parentId, Integer level) {
        List<AppProj> ProjList=null;
        if (parentId == null && level == null) {
            //查找一级节点
            appProj.setProjLevel("1");
            ProjList = baseMapper.list(new Page<AppProj>(current, size), appProj);
        }else
        {//按层级展开节点
            Integer parentLevel=null;
            if(parentId!=null&&!"".equals(parentId)){
                AppProj parentProj=this.getById(parentId);
                parentLevel=Integer.valueOf(parentProj.getProjLevel());
            }
            //只显示自己参与的项目
            String myProj=null;
            String userId = SecurityUtils.getUserId();
            if (!"admin".equals(userId)) {
                myProj=userId;
            }
            ProjList = baseMapper.treeData(parentId,level,parentLevel, myProj);
        }
        if (ProjList != null) {
            List<AppProjVo> projVoList=new ArrayList<>();
            for (AppProj proj :ProjList) {
                AppProjVo appProjVo=new AppProjVo();
                BeanUtils.copyProperties(proj,appProjVo);
                //计算任务数
                Integer taskNum = appTaskService.count(new LambdaQueryWrapper<AppTask>().eq(AppTask::getProjId, proj.getProjId()));
                appProjVo.setTaskNum(taskNum);
                //计算里程碑数
                Integer mptNum = appMptService.count(new LambdaQueryWrapper<AppMpt>().eq(AppMpt::getProjId, proj.getProjId()));
                appProjVo.setMptNum(mptNum);

                projVoList.add(appProjVo);
            }
            return makeOrgTree(projVoList);
        }
        return null;
    }

    /**
     * 生成机构树
     *
     * @param ProjList
     * @return
     */
    public List<ElTree> makeOrgTree(List<AppProjVo> ProjList) {
        Map<String, ElTree> orgMap = new LinkedHashMap<String, ElTree>();
        for (AppProjVo appProj : ProjList) {
            ElTree elTree = new ElTree();
            elTree.setId(appProj.getProjId());
            elTree.setLabel(appProj.getName());
            elTree.setIsLeaf("1".equals(appProj.getIsLeaf()));
            elTree.setData(appProj);
            orgMap.put(appProj.getProjId(), elTree);
            if (CommonUtil.isNotEmptyStr(appProj.getParentProjId()) && orgMap.containsKey(appProj.getParentProjId())) {
                elTree.setParentId(appProj.getParentProjId());
                ElTree parentElTree = orgMap.get(appProj.getParentProjId());
                parentElTree.addChildren(elTree);
            }
        }

        List<ElTree> result = new ArrayList<ElTree>();
        orgMap.forEach((k, v) -> {
            if (CommonUtil.isEmptyStr(v.getParentId())) {
                result.add(v);
            }
        });
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delByIds(String ids) {

        Boolean result = true;
        String[] idsArr = ids.split(",");

        result = isRemove(idsArr);
        if (result == false) {
            return result;
        }
        for (String s:idsArr) {

            //删除项目任务
            if (!"".equals(s)) {
                Map<String, Object> columnMap = new HashMap<>();
                columnMap.put("PROJ_ID", s);
                appTaskService.removeByMap(columnMap);
            }

            AppProj appProj=baseMapper.selectById(s);

            try {
                if (appProj.getMailbox()!=null && !"".equals(appProj.getMailbox())) {
                    mailinaboxUserUtils.addRemove(appProj.getMailbox());
                }
            } catch (Exception e) {
            }

            result= this.removeById(s);

            if (appProj.getParentProjId() != null && !"".equals(appProj.getParentProjId())) {
                inspectParent(appProj.getParentProjId());
            }
        }
        return result;
    }

    private boolean isRemove(String[] idsArr){
        Boolean result = true;
        for (String s:idsArr) {
            AppProj appProj = baseMapper.selectById(s);
            //项目不存在
            if (appProj == null) {
                result = false;
            }
            //超级管理员可删除
            String userId = SecurityUtils.getUserId();
            if(!userId.equals("admin")){
                throw new SysException("不是超级管理员不可以删除项目！");
            }
            //不为叶子节点
            if ("0".equals(appProj.getIsLeaf())) {
                result = false;
            }
        }
        return result;
    }

    //检查父节点是否为子树
    private void inspectParent(String parentId){
        Integer total = this.count(new LambdaQueryWrapper<AppProj>().eq(AppProj::getParentProjId, parentId));
        if (total <= 0) {
            AppProj parentAppProj=baseMapper.selectById(parentId);
            parentAppProj.setIsLeaf(SysConstants.USER_STATUS_1);
            this.updateById(parentAppProj);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AppProj queryById(String id) {
        AppProjVo appProj=new AppProjVo();
        appProj.setProjId(id);
        List<AppProj> appProjList= baseMapper.list(null, appProj);
       if(appProjList.size()>0){
           return appProjList.get(0);
       }
        return null;
    }

    /**
     * 新增机构，自动计算机构级别、机构级次码、是否叶子
     *
     * @param appProj
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAppProj(AppProj appProj) {
        //保存修改项目成员数组，标签数组
        List<SysUser> userList=null;
        List<AppTag> tags=null;
        if(appProj.getUserList()!=null){
            userList=appProj.getUserList();
        }
        if(appProj.getTags()!=null){
            tags=appProj.getTags();
        }

        AppProj proj=this.queryById(appProj.getProjId());
        if(!proj.getName().equals(proj.getName())){
            appLogService.addLog("变更项目 "+proj.getName()+" 更改标题为 "+appProj.getName(),"00",appProj.getProjId());
        }
        //进行中的项目改为不可修改
        if("01".equals(proj.getStatus())){
            appProj.setRevise("0");
        }
        appProj.setUpdateTime(new Date());
        Boolean result = this.updateById(appProj);
        if(result==false){
            return false;
        }

        //判断是否存在非父项目成员
        if (proj.getParentProjId() != null && !"".equals(proj.getParentProjId())) {
            if (!appProjUserService.checkMembers(userList, proj.getParentProjId())) {
                throw new SysException("存在不属于父项目的参与成员！");
            }
            //判断负责人是否为父项目成员
            if (appProj.getMasterUserId() != null && !"".equals(appProj.getMasterUserId())) {
                List<String> projUserIdList = appProjUserService.selectUserIdList(proj.getParentProjId());
                if (!projUserIdList.contains(appProj.getMasterUserId())) {
                    throw new SysException("负责人不属于父项目的参与成员！");
                }
            }
        }

        //删除原项目成员，项目标签
        //添加修改项目成员，项目标签
        if(userList!=null){
            AppProjUser appProjUser=new AppProjUser();
            appProjUser.setProjId(appProj.getProjId());
            appProjUserService.relationDel(appProjUser);
            for (SysUser user:userList) {
                appProjUser.setUserId(user.getUserId());
                appProjUserService.saveAppProjUser(appProjUser);
            }
        }
        if(tags!=null){
            AppProjTag appProjTag=new AppProjTag();
            appProjTag.setProjId(appProj.getProjId());
            appProjTagService.relationDel(appProjTag);
            for (AppTag tag:tags) {
                appProjTag.setTagId(tag.getTagId());
                appProjTagService.saveAppProjTag(appProjTag);
            }
        }

        appLogService.addLog("变更项目内容","00",appProj.getProjId());
        return result;
    }

    /**
     * 待办的
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean wait(String projId) {
        AppProj appProj=this.getById(projId);
        if(appProj==null){
            return false;
        }
        appProj.setStatus("00");
        appProj.setUpdateTime(new Date());
        Boolean result = this.updateById(appProj);

        appLogService.addLog("变更项目状态为 待办的","00",appProj.getProjId());
        return result;
    }
    /**
     * 进行中
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean inProgress(String projId) {
        AppProj appProj=this.getById(projId);
        if(appProj==null){
            return false;
        }
        appProj.setStatus("01");
        appProj.setRevise("0");
        appProj.setWorkStartDate(new Date());
        appProj.setUpdateTime(new Date());
        Boolean result = this.updateById(appProj);

        appLogService.addLog("变更项目状态为 进行中","00",appProj.getProjId());
        return result;
    }
    /**
     * 已完成
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean finish(String projId) {
        AppProj appProj=this.getById(projId);
        if(appProj==null){
            return false;
        }
        appProj.setStatus("02");
        appProj.setWorkEndDate(new Date());
        appProj.setUpdateTime(new Date());
        Boolean result = this.updateById(appProj);

        appLogService.addLog("变更项目状态为 已完成","00",appProj.getProjId());
        return result;
    }
    /**
     * 已终止
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean close(String projId) {
        AppProj appProj=this.getById(projId);
        if(appProj==null){
            return false;
        }
        appProj.setStatus("03");
        appProj.setUpdateTime(new Date());
        Boolean result = this.updateById(appProj);

        appLogService.addLog("变更项目状态为 已终止","00",appProj.getProjId());
        return result;
    }

    /**
     * 已中止
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean suspend(String projId) {
        AppProj appProj=this.getById(projId);
        if(appProj==null){
            return false;
        }
        appProj.setStatus("04");
        appProj.setUpdateTime(new Date());
        Boolean result = this.updateById(appProj);

        appLogService.addLog("变更项目状态为 已中止","00",appProj.getProjId());
        return result;
    }

    /**
     * 面包屑导航
     *
     * @return
     */
    @Override
    public  List<ProjCrumbVo> projCrumb(String projId) {
        List<ProjCrumbVo> result=new ArrayList<>();
        List<ProjCrumbVo> projCrumbVoList=baseMapper.projCrumb(projId);
        if(projCrumbVoList.size()>0){
            if(projCrumbVoList.get(0).getParentProjId()!=null){
                result.addAll(projCrumb(projCrumbVoList.get(0).getParentProjId()));
            }
            result.add(projCrumbVoList.get(0));
        }
//        Collections.reverse(result);
        return result;
    }

    /**
     * 面包屑导航
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void useTemplate(String projId,String dirId) {
       AppProj appProj=this.getById(projId);
       if(appProj==null){
           throw new SysException("选择的项目不存在！");
       }
       AppTemplate appTemplate=new AppTemplate();
       appTemplate.setDirId(dirId);
       List<ElTree> elTreeList=appTemplateService.getTreeData(appTemplate);
       addTemplateTask(elTreeList,appProj,null,new Date());

    }

    private void addTemplateTask(List<ElTree> elTreeList, AppProj appProj,String parentTaskId,Date data){
        for (ElTree e:elTreeList) {
            AppTemplate appTemplate=(AppTemplate) e.getData();
            AppTask appTask=new AppTask();
            String taskId=UUID.randomUUID().toString().replace("-", "").toLowerCase();
            appTask.setTaskId(taskId);
            if(parentTaskId!=null){
                appTask.setParentTaskId(parentTaskId);
            }
            appTask.setName(appTemplate.getName());
            appTask.setTaskType(appTemplate.getTempType());
            appTask.setContent(appTemplate.getContent());
            appTask.setTaskTime(appTemplate.getTaskTime());
            appTask.setMatrix(appTemplate.getMatrix());
            appTask.setStartDate(appTemplate.getStartDate());
            appTask.setEndDate(appTemplate.getEndDate());
            appTask.setOrgId(appTemplate.getOrgId());
            appTask.setProjId(appProj.getProjId());
            appTask.setProjName(appProj.getName());
            //添加创建时间方便后续排序
            Calendar newTime = Calendar.getInstance();
            newTime.setTime(data);
            newTime.add(Calendar.SECOND,1);
            data=newTime.getTime();
            appTask.setCreateTime(newTime.getTime());

            appTaskService.saveAppTask(appTask);
            //保存标签
            if(appTemplate.getTags().size()>0){
                for (AppTag t:appTemplate.getTags()) {
                    AppTaskTag appTaskTag=new AppTaskTag();
                    appTaskTag.setTaskId(taskId);
                    appTaskTag.setTagId(t.getTagId());
                    appTaskTagService.saveAppTaskTag(appTaskTag);
                }
            }
            //保存文档
            List<DocFilePath> docFilePath= new ArrayList<>();
            if(appTemplate.getDocList().size()>0){
                for (AppDoc doc:appTemplate.getDocList()) {
                    docFilePath.addAll(doc.getDocFilePath());
                }
                AppDoc appDoc=new AppDoc();
                appDoc.setDocFilePath(docFilePath);
                appDoc.setDeleted("0");
                appDoc.setName("任务附件");
                appDoc.setDocType("01");
                appDoc.setDocTypeId(taskId);
                appDocService.saveAppDoc(appDoc);
            }

            if(e.getChildren()!=null){
                List<ElTree> elTrees=e.getChildren();
                addTemplateTask(elTrees,appProj,taskId,data);
            }
        }
    }
}
